//+------------------------------------------------------------------+
//|                                                       DXMath.mqh |
//|                             Copyright 2000-2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| DirectX 数学函数                                                 |
//+------------------------------------------------------------------+
//| 移植自 ReactOS 的 C++ 代码，作者 David Adam 和 Tony Wasserka     |
//|                                                                  |
//| https://doxygen.reactos.org/de/d57/                              |
//| dll_2directx_2wine_2d3dx9__36_2math_8c_source.html               |
//|                                                                  |
//| Copyright (C) 2007 David Adam                                    |
//| Copyright (C) 2007 Tony Wasserka                                 |
//+------------------------------------------------------------------+

//--- 数学常量定义
#define DX_PI           3.1415926535897932384626f  // π
#define DX_PI_DIV2      1.5707963267948966192313f  // π/2
#define DX_PI_DIV3      1.0471975511965977461542f  // π/3
#define DX_PI_DIV4      0.7853981633974483096156f  // π/4
#define DX_PI_DIV6      0.5235987755982988730771f  // π/6
#define DX_PI_MUL2      6.2831853071795864769253f  // 2π
#define DXSH_MINORDER   2  // 球谐函数最小阶数
#define DXSH_MAXORDER   6  // 球谐函数最大阶数

//+------------------------------------------------------------------+
//| 前置声明                                                         |
//+------------------------------------------------------------------+
struct DXColor;
struct DXPlane;
struct DXVector2;
struct DXVector3;
struct DXVector4;
struct DXMatrix;
struct DXQuaternion;
struct DViewport;

//+------------------------------------------------------------------+
//| DXColor 结构体                                                   |
//| 用途：表示 RGBA 颜色值                                           |
//+------------------------------------------------------------------+
struct DXColor
{
   float             r;  // 红色分量
   float             g;  // 绿色分量
   float             b;  // 蓝色分量
   float             a;  // 透明度分量
   
   //--- 构造函数
   DXColor(void);
   DXColor(float red, float green, float blue, float alpha);
   DXColor(const DXVector4 &v);
   DXColor(const DXVector3 &v);
   DXColor(const DXColor &c);
};

//+------------------------------------------------------------------+
//| DXPlane 结构体                                                   |
//| 用途：表示平面方程系数 (ax + by + cz + d = 0)                    |
//+------------------------------------------------------------------+
struct DXPlane
{
   float             a;  // x 系数
   float             b;  // y 系数
   float             c;  // z 系数
   float             d;  // 常数项
};

//+------------------------------------------------------------------+
//| DXVector2 结构体                                                 |
//| 用途：表示 2D 向量                                               |
//+------------------------------------------------------------------+
struct DXVector2
{
   float             x;  // x 分量
   float             y;  // y 分量
   
   //--- 构造函数
   DXVector2(void);
   DXVector2(float v);
   DXVector2(float vx, float vy);
   DXVector2(const DXVector3 &v);
   DXVector2(const DXVector4 &v);
};

//+------------------------------------------------------------------+
//| DXVector3 结构体                                                 |
//| 用途：表示 3D 向量                                               |
//+------------------------------------------------------------------+
struct DXVector3
{
   float             x;  // x 分量
   float             y;  // y 分量
   float             z;  // z 分量
   
   //--- 构造函数
   DXVector3(void);
   DXVector3(float v);
   DXVector3(float vx, float vy, float vz);
   DXVector3(const DXVector2 &v);
   DXVector3(const DXVector4 &v);
};

//+------------------------------------------------------------------+
//| DXVector4 结构体                                                 |
//| 用途：表示 4D 向量                                               |
//+------------------------------------------------------------------+
struct DXVector4
{
   float             x;  // x 分量
   float             y;  // y 分量
   float             z;  // z 分量
   float             w;  // w 分量
   
   //--- 构造函数
   DXVector4(void);
   DXVector4(float v);
   DXVector4(float vx, float vy, float vz, float vw);
   DXVector4(const DXVector2 &v);
   DXVector4(const DXVector3 &v);
   DXVector4(const DXVector4 &v);
};

//+------------------------------------------------------------------+
//| DXMatrix 结构体                                                  |
//| 用途：表示 4x4 矩阵                                              |
//+------------------------------------------------------------------+
struct DXMatrix
{
   float             m[4][4];  // 矩阵元素
};

//+------------------------------------------------------------------+
//| DXQuaternion 结构体                                              |
//| 用途：表示四元数 (x, y, z, w)                                    |
//+------------------------------------------------------------------+
struct DXQuaternion
{
   float             x;  // x 分量
   float             y;  // y 分量
   float             z;  // z 分量
   float             w;  // w 分量
};

//+------------------------------------------------------------------+
//| DViewport 结构体                                                 |
//| 用途：表示视口参数                                               |
//+------------------------------------------------------------------+
struct DViewport
{
   ulong             x;       // 左上角 x 坐标
   ulong             y;       // 左上角 y 坐标
   ulong             width;   // 视口宽度
   ulong             height;  // 视口高度
   float             minz;    // 最小深度值
   float             maxz;    // 最大深度值
};

//+------------------------------------------------------------------+
//| DXColor 函数声明                                                 |
//+------------------------------------------------------------------+

/**
 * 将两个颜色值相加
 * @param pout 输出颜色
 * @param pc1 第一个颜色
 * @param pc2 第二个颜色
 */
void DXColorAdd(DXColor &pout, const DXColor &pc1, const DXColor &pc2);

/**
 * 调整颜色对比度
 * @param pout 输出颜色
 * @param pc 输入颜色
 * @param s 对比度缩放因子
 */
void DXColorAdjustContrast(DXColor &pout, const DXColor &pc, float s);

/**
 * 调整颜色饱和度
 * @param pout 输出颜色
 * @param pc 输入颜色
 * @param s 饱和度缩放因子
 */
void DXColorAdjustSaturation(DXColor &pout, const DXColor &pc, float s);

/**
 * 颜色线性插值
 * @param pout 输出颜色
 * @param pc1 起始颜色
 * @param pc2 结束颜色
 * @param s 插值因子 (0.0-1.0)
 */
void DXColorLerp(DXColor &pout, const DXColor &pc1, const DXColor &pc2, float s);

/**
 * 颜色调制（分量相乘）
 * @param pout 输出颜色
 * @param pc1 第一个颜色
 * @param pc2 第二个颜色
 */
void DXColorModulate(DXColor &pout, const DXColor &pc1, const DXColor &pc2);

/**
 * 颜色取反
 * @param pout 输出颜色
 * @param pc 输入颜色
 */
void DXColorNegative(DXColor &pout, const DXColor &pc);

/**
 * 颜色缩放
 * @param pout 输出颜色
 * @param pc 输入颜色
 * @param s 缩放因子
 */
void DXColorScale(DXColor &pout, const DXColor &pc, float s);

/**
 * 颜色相减
 * @param pout 输出颜色
 * @param pc1 被减颜色
 * @param pc2 减去的颜色
 */
void DXColorSubtract(DXColor &pout, const DXColor &pc1, const DXColor &pc2);

/**
 * 计算菲涅尔项
 * @param costheta 入射角余弦
 * @param refractionindex 折射率
 * @return 菲涅尔项值
 */
float DXFresnelTerm(float costheta, float refractionindex);

//+------------------------------------------------------------------+
//| DXVector2 函数声明                                               |
//+------------------------------------------------------------------+

/**
 * 向量加法
 * @param pout 输出向量
 * @param pv1 第一个向量
 * @param pv2 第二个向量
 */
void DXVec2Add(DXVector2 &pout, const DXVector2 &pv1, const DXVector2 &pv2);

/**
 * 计算重心坐标
 * @param pout 输出点
 * @param pv1 第一个点
 * @param pv2 第二个点
 * @param pv3 第三个点
 * @param f 重心坐标参数 f
 * @param g 重心坐标参数 g
 */
void DXVec2BaryCentric(DXVector2 &pout, const DXVector2 &pv1, const DXVector2 &pv2, const DXVector2 &pv3, float f, float g);

/**
 * Catmull-Rom 样条插值
 * @param pout 输出点
 * @param pv0 控制点0
 * @param pv1 控制点1
 * @param pv2 控制点2
 * @param pv3 控制点3
 * @param s 插值参数
 */
void DXVec2CatmullRom(DXVector2 &pout, const DXVector2 &pv0, const DXVector2 &pv1, const DXVector2 &pv2, const DXVector2 &pv3, float s);

/**
 * 计算二维叉积（标量）
 * @param pv1 第一个向量
 * @param pv2 第二个向量
 * @return 叉积结果
 */
float DXVec2CCW(const DXVector2 &pv1, const DXVector2 &pv2);

/**
 * 向量点积
 * @param pv1 第一个向量
 * @param pv2 第二个向量
 * @return 点积结果
 */
float DXVec2Dot(const DXVector2 &pv1, const DXVector2 &pv2);

/**
 * Hermite 样条插值
 * @param pout 输出点
 * @param pv1 起点位置
 * @param pt1 起点切线
 * @param pv2 终点位置
 * @param pt2 终点切线
 * @param s 插值参数
 */
void DXVec2Hermite(DXVector2 &pout, const DXVector2 &pv1, const DXVector2 &pt1, const DXVector2 &pv2, const DXVector2 &pt2, float s);

/**
 * 向量长度
 * @param v 输入向量
 * @return 向量长度
 */
float DXVec2Length(const DXVector2 &v);

/**
 * 向量长度平方
 * @param v 输入向量
 * @return 向量长度平方
 */
float DXVec2LengthSq(const DXVector2 &v);

/**
 * 向量线性插值
 * @param pout 输出向量
 * @param pv1 起始向量
 * @param pv2 结束向量
 * @param s 插值因子
 */
void DXVec2Lerp(DXVector2 &pout, const DXVector2 &pv1, const DXVector2 &pv2, float s);

/**
 * 分量取最大值
 * @param pout 输出向量
 * @param pv1 第一个向量
 * @param pv2 第二个向量
 */
void DXVec2Maximize(DXVector2 &pout, const DXVector2 &pv1, const DXVector2 &pv2);

/**
 * 分量取最小值
 * @param pout 输出向量
 * @param pv1 第一个向量
 * @param pv2 第二个向量
 */
void DXVec2Minimize(DXVector2 &pout, const DXVector2 &pv1, const DXVector2 &pv2);

/**
 * 向量归一化
 * @param pout 输出向量
 * @param pv 输入向量
 */
void DXVec2Normalize(DXVector2 &pout, const DXVector2 &pv);

/**
 * 向量缩放
 * @param pout 输出向量
 * @param pv 输入向量
 * @param s 缩放因子
 */
void DXVec2Scale(DXVector2 &pout, const DXVector2 &pv, float s);

/**
 * 向量减法
 * @param pout 输出向量
 * @param pv1 被减向量
 * @param pv2 减去的向量
 */
void DXVec2Subtract(DXVector2 &pout, const DXVector2 &pv1, const DXVector2 &pv2);

/**
 * 向量变换（齐次坐标）
 * @param pout 输出向量
 * @param pv 输入向量
 * @param pm 变换矩阵
 */
void DXVec2Transform(DXVector4 &pout, const DXVector2 &pv, const DXMatrix &pm);

/**
 * 向量坐标变换（透视除法）
 * @param pout 输出向量
 * @param pv 输入向量
 * @param pm 变换矩阵
 */
void DXVec2TransformCoord(DXVector2 &pout, const DXVector2 &pv, const DXMatrix &pm);

/**
 * 向量法线变换
 * @param pout 输出向量
 * @param pv 输入向量
 * @param pm 变换矩阵
 */
void DXVec2TransformNormal(DXVector2 &pout, const DXVector2 &pv, const DXMatrix &pm);

//+------------------------------------------------------------------+
//| DXVector3 函数声明                                               |
//+------------------------------------------------------------------+

/**
 * 向量加法
 * @param pout 输出向量
 * @param pv1 第一个向量
 * @param pv2 第二个向量
 */
void DXVec3Add(DXVector3 &pout, const DXVector3 &pv1, const DXVector3 &pv2);

/**
 * 计算重心坐标
 * @param pout 输出点
 * @param pv1 第一个点
 * @param pv2 第二个点
 * @param pv3 第三个点
 * @param f 重心坐标参数 f
 * @param g 重心坐标参数 g
 */
void DXVec3BaryCentric(DXVector3 &pout, const DXVector3 &pv1, const DXVector3 &pv2, const DXVector3 &pv3, float f, float g);

/**
 * Catmull-Rom 样条插值
 * @param pout 输出点
 * @param pv0 控制点0
 * @param pv1 控制点1
 * @param pv2 控制点2
 * @param pv3 控制点3
 * @param s 插值参数
 */
void DXVec3CatmullRom(DXVector3 &pout, const DXVector3 &pv0, const DXVector3 &pv1, const DXVector3 &pv2, const DXVector3 &pv3, float s);

/**
 * 向量叉积
 * @param pout 输出向量
 * @param pv1 第一个向量
 * @param pv2 第二个向量
 */
void DXVec3Cross(DXVector3 &pout, const DXVector3 &pv1, const DXVector3 &pv2);

/**
 * 向量点积
 * @param pv1 第一个向量
 * @param pv2 第二个向量
 * @return 点积结果
 */
float DXVec3Dot(const DXVector3 &pv1, const DXVector3 &pv2);

/**
 * Hermite 样条插值
 * @param pout 输出点
 * @param pv1 起点位置
 * @param pt1 起点切线
 * @param pv2 终点位置
 * @param pt2 终点切线
 * @param s 插值参数
 */
void DXVec3Hermite(DXVector3 &pout, const DXVector3 &pv1, const DXVector3 &pt1, const DXVector3 &pv2, const DXVector3 &pt2, float s);

/**
 * 向量长度
 * @param pv 输入向量
 * @return 向量长度
 */
float DXVec3Length(const DXVector3 &pv);

/**
 * 向量长度平方
 * @param pv 输入向量
 * @return 向量长度平方
 */
float DXVec3LengthSq(const DXVector3 &pv);

/**
 * 向量线性插值
 * @param pout 输出向量
 * @param pv1 起始向量
 * @param pv2 结束向量
 * @param s 插值因子
 */
void DXVec3Lerp(DXVector3 &pout, const DXVector3 &pv1, const DXVector3 &pv2, float s);

/**
 * 分量取最大值
 * @极 pout 输出向量
 * @param pv1 第一个向量
 * @param pv2 第二个向量
 */
void DXVec3Maximize(DXVector3 &pout, const DXVector3 &pv1, const DXVector3 &pv2);

/**
 * 分量取最小值
 * @param pout 输出向量
 * @param pv1 第一个向量
 * @param pv2 第二个向量
 */
void DXVec3Minimize(DXVector3 &pout, const DXVector3 &pv1, const DXVector3 &pv2);

/**
 * 向量归一化
 * @param pout 输出向量
 * @param pv 输入向量
 */
void DXVec3Normalize(DXVector3 &pout, const DXVector3 &pv);

/**
 * 投影向量到屏幕空间
 * @param pout 输出向量
 * @param pv 输入向量
 * @param pviewport 视口参数
 * @param pprojection 投影矩阵
 * @param pview 视图矩阵
 * @param pworld 世界矩阵
 */
void DXVec3Project(DXVector3 &pout, const DXVector3 &pv, const DViewport &pviewport, const DXMatrix &pprojection, const DXMatrix &pview, const DXMatrix &pworld);

/**
 * 向量缩放
 * @param pout 输出向量
 * @param pv 输入向量
 * @param s 缩放因子
 */
void DXVec3Scale(DXVector3 &pout, const DXVector3 &pv, float s);

/**
 * 向量减法
 * @param pout 输出向量
 * @param pv1 被减向量
 * @param pv2 减去的向量
 */
void DXVec3Subtract(DXVector3 &pout, const DXVector3 &pv1, const DXVector3 &pv2);

/**
 * 向量变换（齐次坐标）
 * @param pout 输出向量
 * @param pv 输入向量
 * @param pm 变换矩阵
 */
void DXVec3Transform(DXVector4 &pout, const DXVector3 &pv, const DXMatrix &pm);

/**
 * 向量坐标变换（透视除法）
 * @param pout 输出向量
 * @param pv 输入向量
 * @param pm 变换矩阵
 */
void DXVec3TransformCoord(DXVector3 &pout, const DXVector3 &pv, const DXMatrix &pm);

/**
 * 向量法线变换
 * @param pout 输出向量
 * @param pv 输入向量
 * @param pm 变换矩阵
 */
void DXVec3TransformNormal(DXVector3 &pout, const DXVector3 &pv, const DXMatrix &pm);

/**
 * 从屏幕空间反投影到世界空间
 * @param out 输出向量
 * @param v 屏幕空间向量
 * @param viewport 视口参数
 * @param projection 投影矩阵
 * @param view 视图矩阵
 * @param world 世界矩阵
 */
void DXVec3Unproject(DXVector3 &out, const DXVector3 &v, const DViewport &viewport, const DXMatrix &projection, const DXMatrix &view, const DXMatrix &world);

//+------------------------------------------------------------------+
//| DXVector4 函数声明                                               |
//+------------------------------------------------------------------+

/**
 * 向量加法
 * @param pout 输出向量
 * @param pv1 第一个向量
 * @param pv2 第二个向量
 */
void DXVec4Add(DXVector4 &pout, const DXVector4 &pv1, const DXVector4 &pv2);

/**
 * 计算重心坐标
 * @param pout 输出点
 * @param pv1 第一个点
 * @param pv2 第二个点
 * @param pv3 第三个点
 * @param f 重心坐标参数 f
 * @param g 重心坐标参数 g
 */
void DXVec4BaryCentric(DXVector4 &pout, const DXVector4 &pv1, const DXVector4 &pv2, const DXVector4 &pv3, float f, float g);

/**
 * Catmull-Rom 样条插值
 * @param pout 输出点
 * @param pv0 控制点0
 * @param pv1 控制点1
 * @param pv2 控制点2
 * @param pv3 控制点3
 * @param s 插值参数
 */
void DXVec4CatmullRom(DXVector4 &pout, const DXVector4 &pv0, const DXVector4 &pv1, const DXVector4 &pv2, const DXVector4 &pv3, float s);

/**
 * 四维向量叉积
 * @param pout 输出向量
 * @param pv1 第一个向量
 * @param pv2 第二个向量
 * @param pv3 第三个向量
 */
void DXVec4Cross(DXVector4 &pout, const DXVector4 &pv1, const DXVector4 &pv2, const DXVector4 &pv3);

/**
 * 向量点积
 * @param pv1 第一个向量
 * @param pv2 第二个向量
 * @return 点积结果
 */
float DXVec4Dot(const DXVector4 &pv1, const DXVector4 &pv2);

/**
 * Hermite 样条插值
 * @param pout 输出点
 * @param pv1 起点位置
 * @param pt1 起点切线
 * @param pv2 终点位置
 * @param pt2 终点切线
 * @param s 插值参数
 */
void DXVec4Hermite(DXVector4 &pout, const DXVector4 &pv1, const DXVector4 &pt1, const DXVector4 &pv2, const DXVector4 &pt2, float s);

/**
 * 向量长度
 * @param pv 输入向量
 * @return 向量长度
 */
float DXVec4Length(const DXVector4 &pv);

/**
 * 向量长度平方
 * @param pv 输入向量
 * @return 向量长度平方
 */
float DXVec4LengthSq(const DXVector4 &pv);

/**
 * 向量线性插值
 * @param pout 输出向量
 * @param pv1 起始向量
 * @param pv2 结束向量
 * @param s 插值因子
 */
void DXVec4Lerp(DXVector4 &pout, const DXVector4 &pv1, const DXVector4 &pv2, float s);

/**
 * 分量取最大值
 * @param pout 输出向量
 * @param pv1 第一个向量
 * @param pv2 第二个向量
 */
void DXVec4Maximize(DXVector4 &pout, const DXVector4 &pv1, const DXVector4 &pv2);

/**
 * 分量取最小值
 * @param pout 输出向量
 * @param pv1 第一个向量
 * @param pv2 第二个向量
 */
void DXVec4Minimize(DXVector4 &pout, const DXVector4 &pv1, const DXVector4 &pv2);

/**
 * 向量归一化
 * @param pout 输出向量
 * @param pv 输入向量
 */
void DXVec4Normalize(DXVector4 &pout, const DXVector4 &pv);

/**
 * 向量缩放
 * @param pout 输出向量
 * @param pv 输入向量
 * @param s 缩放因子
 */
void DXVec4Scale(DXVector4 &pout, const DXVector4 &pv, float s);

/**
 * 向量减法
 * @param pout 输出向量
 * @param pv1 被减向量
 * @param pv2 减去的向量
 */
void DXVec4Subtract(DXVector4 &pout, const DXVector4 &pv1, const DXVector4 &pv2);

/**
 * 向量变换
 * @param pout 输出向量
 * @param pv 输入向量
 * @param pm 变换矩阵
 */
void DXVec4Transform(DXVector4 &pout, const DXVector4 &pv, const DXMatrix &pm);

//+------------------------------------------------------------------+
//| DXQuaternion 函数声明                                            |
//+------------------------------------------------------------------+

/**
 * 四元数重心坐标插值
 * @param pout 输出四元数
 * @param pq1 第一个四元数
 * @param pq2 第二个四元数
 * @param pq3 第三个四元数
 * @param f 重心坐标参数 f
 * @param g 重心坐标参数 g
 */
void DXQuaternionBaryCentric(DXQuaternion &pout, DXQuaternion &pq1, DXQuaternion &pq2, DXQuaternion &pq3, float f, float g);

/**
 * 四元数共轭
 * @param pout 输出四元数
 * @param pq 输入四元数
 */
void DXQuaternionConjugate(DXQuaternion &pout, const DXQuaternion &pq);

/**
 * 四元数点积
 * @param a 第一个四元数
 * @param b 第二个四元数
 * @return 点积结果
 */
float DXQuaternionDot(DXQuaternion &a, DXQuaternion &b);

/**
 * 四元数指数函数
 * @param out 输出四元数
 * @param q 输入四元数
 */
void DXQuaternionExp(DXQuaternion &out, const DXQuaternion &q);

/**
 * 单位四元数
 * @param out 输出四元数
 */
void DXQuaternionIdentity(DXQuaternion &out);

/**
 * 判断是否为单位四元数
 * @param pq 输入四元数
 * @return 如果是单位四元数返回 true，否则返回 false
 */
bool DXQuaternionIsIdentity(DXQuaternion &pq);

/**
 * 四元数长度
 * @param pq 输入四元数
 * @return 四元数长度
 */
float DXQuaternionLength(const DXQuaternion &pq);

/**
 * 四元数长度平方
 * @param pq 输入四元数
 * @return 四元数长度平方
 */
float DXQuaternionLengthSq(const DXQuaternion &pq);

/**
 * 四元数逆
 * @param pout 输出四元数
 * @param pq 输入四元数
 */
void DXQuaternionInverse(DXQuaternion &pout, const DXQuaternion &pq);

/**
 * 四元数自然对数
 * @param out 输出四元数
 * @param q 输入四元数
 */
void DXQuaternionLn(DXQuaternion &out, const DXQuaternion &q);

/**
 * 四元数乘法
 * @param pout 输出四元数
 * @param pq1 第一个四元数
 * @param pq2 第二个四元数
 */
void DXQuaternionMultiply(DXQuaternion &pout, const DXQuaternion &pq1, const DXQuaternion &pq2);

/**
 * 四元数归一化
 * @param out 输出四元数
 * @param q 输入四元数
 */
void DXQuaternionNormalize(DXQuaternion &out, const DXQuaternion &q);

/**
 * 绕轴旋转四元数
 * @param out 输出四元数
 * @param v 旋转轴
 * @param angle 旋转角度
 */
void DXQuaternionRotationAxis(DXQuaternion &out, const DXVector3 &v, float angle);

/**
 * 从旋转矩阵创建四元数
 * @param out 输出四元数
 * @param m 旋转矩阵
 */
void DXQuaternionRotationMatrix(DXQuaternion &out, const DXMatrix &m);

/**
 * 从欧拉角创建四元数
 * @param out 输出四元数
 * @param yaw 偏航角
 * @param pitch 俯仰角
 * @param roll 翻滚角
 */
void DXQuaternionRotationYawPitchRoll(DXQuaternion &out, float yaw, float pitch, float roll);

/**
 * 四元数球面线性插值
 * @param out 输出四元数
 * @param q1 起始四元数
 * @param q2 结束四元数
 * @param t 插值因子
 */
void DXQuaternionSlerp(DXQuaternion &out, DXQuaternion &q1, DXQuaternion &q2, float t);

/**
 * 四元数样条插值
 * @param pout 输出四元数
 * @param pq1 第一个四元数
 * @param pq2 第二个四元数
 * @param pq3 第三个四元数
 * @param pq4 第四个四元数
 * @param t 插值参数
 */
void DXQuaternionSquad(DXQuaternion &pout, DXQuaternion &pq1, DXQuaternion &pq2, DXQuaternion &pq3, DXQuaternion &pq4, float t);

/**
 * 设置四元数样条插值控制点
 * @param paout 输出控制点 A
 * @param pbout 输出控制点 B
 * @param pcout 输出控制点 C
 * @param pq0 第一个四元数
 * @param pq1 第二个四元数
 * @param pq2 第三个四元数
 * @param pq3 第四个四元数
 */
void DXQuaternionSquadSetup(DXQuaternion &paout, DXQuaternion &pbout, DXQuaternion &pcout, DXQuaternion &pq0, DXQuaternion &pq1, DXQuaternion &pq2, DXQuaternion &pq3);

/**
 * 四元数转轴角表示
 * @param pq 输入四元数
 * @param paxis 输出旋转轴
 * @param pangle 输出旋转角度
 */
void DXQuaternionToAxisAngle(const DXQuaternion &pq, DXVector3 &paxis, float &pangle);

/**
 * 四元数带缩放因子的加法
 * @param q1 第一个四元数
 * @param q2 第二个四元数
 * @param add 缩放因子
 * @return 结果四元数
 */
DXQuaternion add_diff(const DXQuaternion &q1, const DXQuaternion &q2, const float add);

//+------------------------------------------------------------------+
//| DXMatrix 函数声明                                                |
//+------------------------------------------------------------------+

/**
 * 单位矩阵
 * @param out 输出矩阵
 */
void DXMatrixIdentity(DXMatrix &out);

/**
 * 判断是否是单位矩阵
 * @param pm 输入矩阵
 * @return 如果是单位矩阵返回 true，否则返回 false
 */
bool DXMatrixIsIdentity(DXMatrix &pm);

/**
 * 创建仿射变换矩阵
 * @param out 输出矩阵
 * @param scaling 缩放因子
 * @param rotationcenter 旋转中心
 * @param rotation 旋转四元数
 * @param translation 平移向量
 */
void DXMatrixAffineTransformation(DXMatrix &out, float scaling, const DXVector3 &rotationcenter, const DXQuaternion &rotation, const DXVector3 &translation);

/**
 * 创建 2D 仿射变换矩阵
 * @param out 输出矩阵
 * @param scaling 缩放因子
 * @param rotationcenter 旋转中心
 * @param rotation 旋转角度
 * @param translation 平移向量
 */
void DXMatrixAffineTransformation2D(DXMatrix &out, float scaling, const DXVector2 &rotationcenter, float rotation, const DXVector2 &translation);

/**
 * 矩阵分解为缩放、旋转和平移
 * @param poutscale 输出缩放向量
 * @param poutrotation 输出旋转四元数
 * @param pouttranslation 输出平移向量
 * @param pm 输入矩阵
 * @return 成功返回 0，失败返回错误码
 */
int DXMatrixDecompose(DXVector3 &poutscale, DXQuaternion &poutrotation, DXVector3 &pouttranslation, const DXMatrix &pm);

/**
 * 矩阵行列式
 * @param pm 输入矩阵
 * @return 行列式值
 */
float DXMatrixDeterminant(const DXMatrix &pm);

/**
 * 矩阵求逆
 * @param pout 输出矩阵
 * @param pdeterminant 输出行列式值
 * @param pm 输入矩阵
 */
void DXMatrixInverse(DXMatrix &pout, float &pdeterminant, const DXMatrix &pm);

/**
 * 创建左手坐标系观察矩阵
 * @param out 输出矩阵
 * @param eye 摄像机位置
 * @param at 观察目标
 * @param up 上向量
 */
void DXMatrixLookAtLH(DXMatrix &out, const DXVector3 &eye, const DXVector3 &at, const DXVector3 &up);

/**
 * 创建右手坐标系观察矩阵
 * @param out 输出矩阵
 * @param eye 摄像机位置
 * @param at 观察目标
 * @param up 上向量
 */
void DXMatrixLookAtRH(DXMatrix &out, const DXVector3 &eye, const DXVector3 &at, const DXVector3 &up);

/**
 * 矩阵乘法
 * @param pout 输出矩阵
 * @param pm1 第一个矩阵
 * @param pm2 第二个矩阵
 */
void DXMatrixMultiply(DXMatrix &pout, const DXMatrix &pm1, const DXMatrix &pm2);

/**
 * 转置矩阵乘法
 * @param pout 输出矩阵
 * @param pm1 第一个矩阵
 * @param pm2 第二个矩阵
 */
void DXMatrixMultiplyTranspose(DXMatrix &pout, const DXMatrix &pm1, const DXMatrix &pm2);

/**
 * 创建左手正交投影矩阵
 * @param pout 输出矩阵
 * @param w 宽度
 * @param h 高度
 * @param zn 近平面
 * @param zf 远平面
 */
void DXMatrixOrthoLH(DXMatrix &pout, float w, float h, float zn, float zf);

/**
 * 创建左手自定义正交投影矩阵
 * @param pout 输出矩阵
 * @param l 左边界
 * @param r 右边界
 * @param b 下边界
 * @param t 上边界
 * @param zn 近平面
 * @param zf 远平面
 */
void DXMatrixOrthoOffCenterLH(DXMatrix &pout, float l, float r, float b, float t, float zn, float zf);

/**
 * 创建右手自定义正交投影矩阵
 * @param pout 输出矩阵
 * @param l 左边界
 * @param r 右边界
 * @param b 下边界
 * @param t 上边界
 * @param zn 近平面
 * @param zf 远平面
 */
void DXMatrixOrthoOffCenterRH(DXMatrix &pout, float l, float r, float b, float t, float zn, float zf);

/**
 * 创建右手正交投影矩阵
 * @param pout 输出矩阵
 * @param w 宽度
 * @param h 高度
 * @param zn 近平面
 * @param zf 远平面
 */
void DXMatrixOrthoRH(DXMatrix &pout, float w, float h, float zn, float zf);

/**
 * 创建左手透视投影矩阵（基于视野）
 * @param pout 输出矩阵
 * @param fovy 垂直视野（弧度）
 * @param aspect 宽高比
 * @param zn 近平面
 * @param zf 远平面
 */
void DXMatrixPerspectiveFovLH(DXMatrix &pout, float fovy, float aspect, float zn, float zf);

/**
 * 创建右手透视投影矩阵（基于视野）
 * @param pout 输出矩阵
 * @param fovy 垂直视野（弧度）
 * @param aspect 宽高比
 * @param zn 近平面
 * @param zf 远平面
 */
void DXMatrixPerspectiveFovRH(DXMatrix &pout, float fovy, float aspect, float zn, float zf);

/**
 * 创建左手透视投影矩阵
 * @param pout 输出矩阵
 * @param w 宽度
 * @param h 高度
 * @param zn 近平面
 * @param zf 远平面
 */
void DXMatrixPerspectiveLH(DXMatrix &pout, float w, float h, float zn, float zf);

/**
 * 创建左手自定义透视投影矩阵
 * @param pout 输出矩阵
 * @param l 左边界
 * @param r 右边界
 * @param b 下边界
 * @param t 上边界
 * @param zn 近平面
 * @param zf 远平面
 */
void DXMatrixPerspectiveOffCenterLH(DXMatrix &pout, float l, float r, float b, float t, float zn, float zf);

/**
 * 创建右手自定义透视投影矩阵
 * @param pout 输出矩阵
 * @param l 左边界
 * @param r 右边界
 * @param b 下边界
 * @param t 上边界
 * @param zn 近平面
 * @param zf 远平面
 */
void DXMatrixPerspectiveOffCenterRH(DXMatrix &pout, float l, float r, float b, float t, float zn, float zf);

/**
 * 创建右手透视投影矩阵
 * @param pout 输出矩阵
 * @param w 宽度
 * @param h 高度
 * @param zn 近平面
 * @param zf 远平面
 */
void DXMatrixPerspectiveRH(DXMatrix &pout, float w, float h, float zn, float zf);

/**
 * 创建反射矩阵
 * @param pout 输出矩阵
 * @param pplane 反射平面
 */
void DXMatrixReflect(DXMatrix &pout, const DXPlane &pplane);

/**
 * 绕轴旋转矩阵
 * @param out 输出矩阵
 * @param v 旋转轴
 * @param angle 旋转角度
 */
void DXMatrixRotationAxis(DXMatrix &out, const DXVector3 &v, float angle);

/**
 * 从四元数创建旋转矩阵
 * @param pout 输出矩阵
 * @param pq 输入四元数
 */
void DXMatrixRotationQuaternion(DXMatrix &pout, const DXQuaternion &pq);

/**
 * 绕 X 轴旋转矩阵
 * @param pout 输出矩阵
 * @param angle 旋转角度
 */
void DXMatrixRotationX(DXMatrix &pout, float angle);

/**
 * 绕 Y 轴旋转矩阵
 * @param pout 输出矩阵
 * @param angle 旋转角度
 */
void DXMatrixRotationY(DXMatrix &pout, float angle);

/**
 * 从欧拉角创建旋转矩阵
 * @param out 输出矩阵
 * @param yaw 偏航角
 * @param pitch 俯仰角
 * @param roll 翻滚角
 */
void DXMatrixRotationYawPitchRoll(DXMatrix &out, float yaw, float pitch, float roll);

/**
 * 绕 Z 轴旋转矩阵
 * @param pout 输出矩阵
 * @param angle 旋转角度
 */
void DXMatrixRotationZ(DXMatrix &pout, float angle);

/**
 * 缩放矩阵
 * @param pout 输出矩阵
 * @param sx X 轴缩放因子
 * @param sy Y 轴缩放因子
 * @param sz Z 轴缩放因子
 */
void DXMatrixScaling(DXMatrix &pout, float sx, float sy, float sz);

/**
 * 阴影矩阵
 * @param pout 输出矩阵
 * @param plight 光源位置
 * @param pplane 阴影平面
 */
void DXMatrixShadow(DXMatrix &pout, const DXVector4 &plight, const DXPlane &pplane);

/**
 * 创建变换矩阵
 * @param pout 输出矩阵
 * @param pscalingcenter 缩放中心
 * @param pscalingrotation 缩放旋转
 * @param pscaling 缩放因子
 * @param protationcenter 旋转中心
 * @param protation 旋转四元数
 * @param ptranslation 平移向量
 */
void DXMatrixTransformation(DXMatrix &pout, const DXVector3 &pscalingcenter, const DXQuaternion &pscalingrotation, const DXVector3 &pscaling, const DXVector3 &protationcenter, const DXQuaternion &protation, const DXVector3 &ptranslation);

/**
 * 创建 2D 变换矩阵
 * @param pout 输出矩阵
 * @param pscalingcenter 缩放中心
 * @param scalingrotation 缩放旋转角度
 * @param pscaling 缩放因子
 * @param protationcenter 旋转中心
 * @param rotation 旋转角度
 * @param ptranslation 平移向量
 */
void DXMatrixTransformation2D(DXMatrix &pout, const DXVector2 &pscalingcenter, float scalingrotation, const DXVector2 &pscaling, const DXVector2 &protationcenter, float rotation, const DXVector2 &ptranslation);

/**
 * 平移矩阵
 * @param pout 输出矩阵
 * @param x X 轴平移量
 * @param y Y 轴平移量
 * @param z Z 轴平移量
 */
void DXMatrixTranslation(DXMatrix &pout, float x, float y, float z);

/**
 * 矩阵转置
 * @param pout 输出矩阵
 * @param pm 输入矩阵
 */
void DXMatrixTranspose(DXMatrix &pout, const DXMatrix &pm);

//+------------------------------------------------------------------+
//| DXPlane 函数声明                                                 |
//+------------------------------------------------------------------+

/**
 * 平面点积
 * @param p1 平面
 * @param p2 点
 * @return 点积结果
 */
float DXPlaneDot(const DXPlane &p1, const DXVector4 &p2);

/**
 * 平面与坐标点积
 * @param pp 平面
 * @param pv 点
 * @return 点积结果
 */
float DXPlaneDotCoord(const DXPlane &pp, const DXVector4 &pv);

/**
 * 平面与法线点积
 * @param pp 平面
 * @param pv 法线向量
 * @return 点积结果
 */
float DXPlaneDotNormal(const DXPlane &pp, const DXVector4 &pv);

/**
 * 从点和法线创建平面
 * @param pout 输出平面
 * @param pvpoint 点
 * @param pvnormal 法线
 */
void DXPlaneFromPointNormal(DXPlane &pout, const DXVector3 &pvpoint, const DXVector3 &pvnormal);

/**
 * 从三点创建平面
 * @param pout 输出平面
 * @param pv1 点1
 * @param pv2 点2
 * @param pv3 点3
 */
void DXPlaneFromPoints(DXPlane &pout, const DXVector3 &pv1, const DXVector3 &pv2, const DXVector3 &pv3);

/**
 * 平面与直线交点
 * @param pout 输出交点
 * @param pp 平面
 * @param pv1 直线起点
 * @param pv2 直线终点
 */
void DXPlaneIntersectLine(DXVector3 &pout, const DXPlane &pp, const DXVector3 &pv1, const DXVector3 &pv2);

/**
 * 平面归一化
 * @param out 输出平面
 * @param p 输入平面
 */
void DXPlaneNormalize(DXPlane &out, const DXPlane &p);

/**
 * 平面缩放
 * @param pout 输出平面
 * @param p 输入平面
 * @param s 缩放因子
 */
void DXPlaneScale(DXPlane &pout, const DXPlane &p, float s);

/**
 * 平面变换
 * @param pout 输出平面
 * @param pplane 输入平面
 * @param pm 变换矩阵
 */
void DXPlaneTransform(DXPlane &pout, const DXPlane &pplane, const DXMatrix &pm);

//+------------------------------------------------------------------+
//| 球谐函数声明                                                     |
//+------------------------------------------------------------------+

/**
 * 球谐函数加法
 * @param out 输出系数数组
 * @param order 阶数
 * @param a 第一组系数
 * @param b 第二组系数
 */
void DXSHAdd(float &out[], int order, const float &a[], const float &b[]);

/**
 * 球谐函数点积
 * @param order 阶数
 * @param a 第一组系数
 * @param b 第二组系数
 * @return 点积结果
 */
float DXSHDot(int order, const float &a[], const float &b[]);

/**
 * 计算锥形光源的球谐系数
 * @param order 阶数
 * @param dir 方向
 * @param radius 半径
 * @param Rintensity 红色强度
 * @param Gintensity 绿色强度
 * @param Bintensity 蓝色强度
 * @param rout 红色输出系数
 * @param gout 绿色输出系数
 * @param bout 蓝色输出系数
 * @return 成功返回 0
 */
int DXSHEvalConeLight(int order, const DXVector3 &dir, float radius, float Rintensity, float Gintensity, float Bintensity, float &rout[], float &gout[], float &bout[]);

/**
 * 计算方向的球谐系数
 * @param out 输出系数
 * @param order 阶数
 * @param dir 方向
 */
void DXSHEvalDirection(float &out[], int order, const DXVector3 &dir);

/**
 * 计算方向光源的球谐系数
 * @param order 阶数
 * @param dir 方向
 * @param Rintensity 红色强度
 * @param Gintensity 绿色强度
 * @param Bintensity 蓝色强度
 * @param rout 红色输出系数
 * @param gout 绿色输出系数
 * @param bout 蓝色输出系数
 * @return 成功返回 0
 */
int DXSHEvalDirectionalLight(int order, const DXVector3 &dir, float Rintensity, float Gintensity, float Bintensity, float &rout[], float &gout[], float &bout[]);

/**
 * 计算半球光源的球谐系数
 * @param order 阶数
 * @param dir 方向
 * @param top 顶部颜色
 * @param bottom 底部颜色
 * @param rout 红色输出系数
 * @param gout 绿色输出系数
 * @param bout 蓝色输出系数
 * @return 成功返回 0
 */
int DXSHEvalHemisphereLight(int order, const DXVector3 &dir, DXColor &top, DXColor &bottom, float &rout[], float &gout[], float &bout[]);

/**
 * 计算球形光源的球谐系数
 * @param order 阶数
 * @param dir 方向
 * @param radius 半径
 * @param Rintensity 红色强度
 * @param Gintensity 绿色强度
 * @param Bintensity 蓝色强度
 * @param rout 红色输出系数
 * @param gout 绿色输出系数
 * @param bout 蓝色输出系数
 * @return 成功返回 0
 */
int DXSHEvalSphericalLight(int order, const DXVector3 &dir, float radius, float Rintensity, float Gintensity, float Bintensity, float &rout[], float &gout[], float &bout[]);

/**
 * 二阶球谐函数乘法
 * @param out 输出系数
 * @param a 第一组系数
 * @param b 第二组系数
 */
void DXSHMultiply2(float &out[], const float &a[], const float &b[]);

/**
 * 三阶球谐函数乘法
 * @param out 输出系数
 * @param a 第一组系数
 * @param b 第二组系数
 */
void DXSHMultiply3(float &out[], const float &a[], const float &b[]);

/**
 * 四阶球谐函数乘法
 * @param out 输出系数
 * @param a 第一组系数
 * @param b 第二组系数
 */
void DXSHMultiply4(float &out[], const float &a[], const float &b[]);

/**
 * 球谐函数旋转
 * @param out 输出系数
 * @param order 阶数
 * @param matrix 旋转矩阵
 * @param in 输入系数
 */
void DXSHRotate(float &out[], int order, const DXMatrix &matrix, const float &in[]);

/**
 * 球谐函数绕 Z 轴旋转
 * @param out 输出系数
 * @param order 阶数
 * @param angle 旋转角度
 * @param in 输入系数
 */
void DXSHRotateZ(float &out[], int order, float angle, const float &in[]);

/**
 * 球谐函数缩放
 * @param out 输出系数
 * @param order 阶数
 * @param a 输入系数
 * @param scale 缩放因子
 */
void DXSHScale(float &out[], int order, const float &a[], const float scale);

//+------------------------------------------------------------------+
//| 标量函数声明                                                     |
//+------------------------------------------------------------------+

/**
 * 标量线性插值
 * @param val1 起始值
 * @param val2 结束值
 * @param s 插值因子
 * @return 插值结果
 */
float DXScalarLerp(const float val1, const float val2, float s);

/**
 * 标量偏置缩放
 * @param val 输入值
 * @param bias 偏置值
 * @param scale 缩放因子
 * @return 结果值
 */
float DXScalarBiasScale(const float val, const float bias, const float scale);
//+------------------------------------------------------------------+